/*
 * Reksio - Memory Map Editor
 * Copyright (C) 2023 CERN
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * In applying this licence, CERN does not waive the privileges and immunities
 * granted to it by virtue of its status as an Intergovernmental Organization or
 * submit itself to any jurisdiction.
 */

#include "attributevalidator.h"
#include "validator.h"
#include "attributecontainervalidator.h"
#include "pythonaction.h"
#include <QDebug>
const std::vector<std::unique_ptr<INodeRuleValidator> > &AttributeValidator::getValidators() const
{
    return _validators;
}

std::vector<std::unique_ptr<INodeRuleValidator> > &AttributeValidator::getValidators()
{
    return _validators;
}


void AttributeValidator::setup(const YAML::Node &schema_node)
{
    if(!schema_node.IsMap())
        return;
    for(const auto& kv: schema_node)
    {
        const std::string& key = kv.first.as<std::string>();
        if(key == "visible")
            setVisible(kv.second.as<bool>());
        else if (key == "editable")
            setEditable(kv.second.as<bool>());
        else if (key == "removable")
            setRemovable(kv.second.as<bool>());
        else if (key == "addable")
            setAddable(kv.second.as<bool>());
        else if (key == "tooltip")
            setToolTip(kv.second.as<std::string>());
        else if (key == "default")
            setDefaultValue(kv.second.as<std::string>());
        else if (key == "py_default")
            _py_dynamic_default_value_module = kv.second.as<std::string>();
        else if (key == "deprecated")
            setDeprecated(kv.second.as<bool>());
        else if (key == "deprecated_msg")
            setDeprecatedMessage(kv.second.as<std::string>());
    }
}

const std::string &AttributeValidator::getName() const
{
    return _name;
}

std::vector<std::string> AttributeValidator::getFullName() const
{
    std::vector<std::string> full_names = _parent->getFullName();
    full_names.push_back(getName());
    return full_names;
}

bool AttributeValidator::isRequired() const
{
    return _required;
}

bool AttributeValidator::isVisible() const
{
    return _visible;
}

void AttributeValidator::setVisible(const bool visible)
{
    _visible = visible;
}

bool AttributeValidator::isEditable() const
{
    return _editable;
}

void AttributeValidator::setEditable(const bool editable)
{
    _editable = editable;
}

bool AttributeValidator::isAddable() const
{
    return _addable;
}

void AttributeValidator::setAddable(const bool addable)
{
    _addable = addable;
}

bool AttributeValidator::isRemovable() const
{
    return _removable;
}

void AttributeValidator::setRemovable(const bool removable)
{
    _removable = removable;
}

const std::string &AttributeValidator::getToolTip() const
{
    return _tooltip;
}

void AttributeValidator::setToolTip(const std::string &tooltip)
{
    _tooltip = tooltip;
}

const std::string &AttributeValidator::getDefaultValue() const
{
    return _default_value;
}

void AttributeValidator::setDefaultValue(const std::string &value)
{
    _default_value = value;
}

bool AttributeValidator::hasDynamicDefaultValue() const
{
    return !_py_dynamic_default_value_module.empty();
}

std::string AttributeValidator::getDynamicDefaultValue()
{
    try
    {
        return python_action(_py_dynamic_default_value_module, "get_default_value", _name).cast<std::string>();
    }
    catch (const py::cast_error&)
    {
        return "";
    }
}

bool AttributeValidator::isDeprecated() const
{
    return _deprecated;
}

void AttributeValidator::setDeprecated(bool deprecated)
{
    _deprecated = deprecated;
}

const std::string &AttributeValidator::getDeprecatedMessage() const
{
    return _deprecated_msg;
}

void AttributeValidator::setDeprecatedMessage(const std::string &msg)
{
    _deprecated_msg = msg;
}

AttributeContainerValidator *AttributeValidator::getParent() const
{
    return _parent;
}

void AttributeValidator::setParent(AttributeContainerValidator *validator)
{
    _parent = validator;
}

const std::string AttributeValidator::getAttributeType() const
{
    NodeTypeValidator* type_val = nullptr;
    const auto& type_validator = getValidator(type_val);
    if(type_validator)
    {
        return type_validator->getTargetType();
    }
    return "str";
}

AttributeValidator::AttributeValidator(const std::string& name, std::vector<std::unique_ptr<INodeRuleValidator> >&& validators):
    _parent(nullptr),
    _validators(std::move(validators)),
    _name(name)
{
    NodeRequiredValidator* required_val = nullptr;
    const auto& required_validator = getValidator(required_val);
    if(required_validator)
    {
        _required = required_validator->isRequired();
    }
    else
    {
        _required = false;
    }
}
